package top.wilsonlv.jaguar.cloud.auth.config;

import groovy.lang.GroovyClassLoader;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
import top.wilsonlv.jaguar.cloud.auth.properties.FeignClientServiceMeta;
import top.wilsonlv.jaguar.cloud.auth.properties.JaguarAuthProperties;
import top.wilsonlv.jaguar.cloud.auth.sdk.spi.SecurityUserService;
import top.wilsonlv.jaguar.openfeign.component.FeignClientRegister;

import java.beans.Introspector;
import java.io.IOException;
import java.io.StringWriter;

/**
 * @author lvws
 * @since 2022/1/4
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class FeignClientServiceClassLoader implements InitializingBean {

    private final JaguarAuthProperties jaguarAuthProperties;

    private final VelocityEngine velocityEngine;

    private final GroovyClassLoader groovyClassLoader;

    private final FeignClientRegister feignClientRegister;

    @Override
    public void afterPropertiesSet() {
        if (jaguarAuthProperties.getSecurityUserServices() != null) {
            Template template = velocityEngine.getTemplate("vm/SecurityUserServiceImpl.vm");
            for (FeignClientServiceMeta serviceInfo : jaguarAuthProperties.getSecurityUserServices()) {
                loadClass(template, serviceInfo);
            }
        }
    }

    private void loadClass(Template template, FeignClientServiceMeta serviceInfo) {
        VelocityContext velocityContext = new VelocityContext();
        velocityContext.put("className", serviceInfo.getClassName());
        velocityContext.put("urlPrefix", serviceInfo.getUrlPrefix());

        String classStr;
        try (StringWriter stringWriter = new StringWriter()) {
            template.merge(velocityContext, stringWriter);
            classStr = stringWriter.toString();
        } catch (IOException e) {
            throw new BeanCreationException(e.getMessage(), e);
        }

        @SuppressWarnings("unchecked")
        Class<SecurityUserService> clazz = groovyClassLoader.parseClass(classStr);

        String beanName = Introspector.decapitalize(clazz.getSimpleName());
        String contextId = serviceInfo.getContextId() != null ? serviceInfo.getContextId() : beanName;

        feignClientRegister.registerFeignClient(beanName, clazz, serviceInfo.getServerName(), contextId);
    }

}
